<template>
  <div id="main" class="view-editable">
    <mr-container
      :id="page.id"
      :style="styles"
      :zoom="zoom"
      :active-elements="selectedElements"
      @arrows="arrowsHandler"
      @moving="movingHandler"
      @movestop="moveStopHandler"
      @resizestop="resizeStopHandler"
      @selectstop="selectStopHandler"
      @clearselection="clearSelectionHandler"
      @delete="deleteHandler"
      @copy="copyHandler"
      @cut="cutHandler"
      @paste="pasteHandler"
      @drop="dropHandler"
      @undo="$root.$emit('undo')"
      @redo="$root.$emit('redo')"
    >
      <stage-el v-for="element in page.children" :key="element.id" :elem="element" />
    </mr-container>
  </div>
</template>
<script>
import cloneDeep from 'clone-deep'
import elementsFromPoint from '@/polyfills/elementsFromPoint'
import MrContainer from './MrContainer'
import StageEl from './StageEl'
import { mapState, mapActions, mapMutations } from 'vuex'
import { getComputedProp, fixElementToParentBounds } from '@/helpers/positionDimension'
export default {
  name: 'MainRight',
  components: { MrContainer, StageEl },
  data() {
    return {
      clipboard: [],
      dropContainer: null
    }
  },
  computed: {
    ...mapState({
      selectedElements: state => state.screen.selectedElements || [],
      zoom: state => state.screen.editorZoom,
      pageStyle: state => state.screen.screenOptions.style,
      page: state => state.screen.pages[0]
    }),
    styles() {
      return {
        ...this.pageStyle,
        height: this.pageStyle.height + 'px',
        width: this.pageStyle.width + 'px',
        transform: 'scale(' + this.zoom + ')',
        top: '16px',
        left: '16px',
        'background-size': '100% 100%',
        'background': '#2931427a'
      }
    }
  },
  mounted() {
  },
  methods: {
    ...mapActions({
      moveElement: 'screen/moveElement',
      resizeElement: 'screen/resizeElement',
      rebaseSelectedElements: 'screen/rebaseSelectedElements',
      registerElement: 'screen/registerElement',
      removeElement: 'screen/removeElement'
    }),
    ...mapMutations({
      _addSelectedElements: 'screen/_addSelectedElements',
      _clearSelectedElements: 'screen/_clearSelectedElements'
    }),
    clearSelectionHandler() {
      if (this.selectedElements.length > 0) this._clearSelectedElements()
    },

    deleteHandler() {
      if (this.selectedElements.length > 0) {
        this.selectedElements.map(el => this.removeElement({ page: this.page, elId: el.id }))
      }
    },

    copyHandler() {
      if (this.selectedElements.length > 0) {
        this.clipboard = []
        this.selectedElements.map(el => this.clipboard.push(cloneDeep(el)))
      }
    },

    cutHandler() {
      if (this.selectedElements.length > 0) {
        this.clipboard = []
        this.selectedElements.map(el => {
          this.clipboard.push(cloneDeep(el))
          this.removeElement({ page: this.page, elId: el.id })
        })
      }
    },

    pasteHandler() {
      if (this.clipboard.length > 0) {
        this.clipboard.map(el => {
          this.registerElement({ pageId: this.page.id, el, global: el.global })
        })
      }
    },
    dropHandler(e) {
      const mainContainer = document.getElementById('main')
      let element = JSON.parse(e.dataTransfer.getData('text/plain'))
      const height = getComputedProp('height', element, this.page)
      const width = getComputedProp('width', element, this.page)
      let top = e.pageY + mainContainer.scrollTop - mainContainer.offsetTop - this.$el.offsetTop - (height / 2)
      let left = e.pageX + mainContainer.scrollLeft - mainContainer.offsetLeft - this.$el.offsetLeft - (width / 2)

      // Correct drop positions based on the editorZoom
      top = Math.round(top / this.zoom)
      left = Math.round(left / this.zoom)

      const fixedElement = fixElementToParentBounds({ top, left, height, width }, this.page)
      element = { ...element, ...fixedElement }

      this.registerElement({ pageId: this.page.id, el: element, global: e.shiftKey })
    },
    selectStopHandler(selectionBox) {
      if ((selectionBox.top === selectionBox.bottom && selectionBox.left === selectionBox.right) ||
          (this.page.children.length === 0)) return

      const selectedElements = []
      this.page.children.forEach(childEl => {
        const child = childEl

        const childTop = getComputedProp('top', child)
        const childLeft = getComputedProp('left', child)
        const childBottom = getComputedProp('height', child, this.page) + childTop
        const childRight = getComputedProp('width', child, this.page) + childLeft

        if (((childTop <= selectionBox.bottom) && (childLeft <= selectionBox.right) &&
            (childBottom >= selectionBox.top) && (childRight >= selectionBox.left)) ||
            ((childTop <= selectionBox.bottom) && (childRight >= selectionBox.left) &&
            (childBottom >= selectionBox.top) && (childLeft <= selectionBox.right))) {
          selectedElements.push(child)
        }
      })

      if (selectedElements.length > 0) {
        this._addSelectedElements(selectedElements)
      }
    },
    resizeStopHandler(resStopData) {
      resStopData.map(resElData => this.resizeElement({ ...resElData, pageId: this.page.id }))
      this.rebaseSelectedElements()
    },
    movingHandler(absMouseX, absMouseY) {
      this.dropContainer = this.getContaineggOnPoint(absMouseX, absMouseY)
      this.toggleDroppableCursor(!!this.dropContainer)
    },
    moveStopHandler(moveStopData) {
      const containegg = this.getContaineggOnPoint(moveStopData.absMouseX, moveStopData.absMouseY)
      const parentId = containegg ? containegg.id : null

      moveStopData.moveElData.map(moveData => this.moveElement({
        ...moveData,
        pageId: this.page.id,
        parentId,
        mouseX: moveStopData.relMouseX,
        mouseY: moveStopData.relMouseY
      }))

      this.rebaseSelectedElements()
      this.toggleDroppableCursor(false)
      this.dropContainer = null
    },
    toggleDroppableCursor(isDroppable) {
      isDroppable
        ? document.documentElement.classList.add('droppable')
        : document.documentElement.classList.remove('droppable')
    },
    getContaineggOnPoint(x, y) {
      const movingEggs = this.selectedElements
      const parentsIds = movingEggs.map(egg => egg.id.substring(0, egg.id.lastIndexOf('.')))
      const commonParentId = parentsIds.every((val, i, arr) => val === arr[0]) ? parentsIds[0] : null
      const elementsOnPoint = elementsFromPoint(x, y)

      for (const el of elementsOnPoint) {
        if (el.id === commonParentId) return null
        if ((el.dataset.mrContainer) ||
          (
            (el.dataset.containegg) &&
            (!el.dataset.componegg) &&
            (movingEggs.every(egg => !el.id.includes(egg.id)))
          )
        ) return el
      }
      return null
    },
    arrowsHandler({ direction, shiftKey }) {
      if (this.selectedElements.length > 0) {
        const diff = shiftKey ? 10 : 1
        let addedTop = 0
        let addedBottom = 0
        let addedLeft = 0
        let addedRight = 0

        switch (direction) {
          case 'up': addedTop -= diff; addedBottom += diff; addedLeft = addedRight = null; break
          case 'down': addedBottom -= diff; addedTop += diff; addedLeft = addedRight = null; break
          case 'left': addedLeft -= diff; addedRight += diff; addedTop = addedBottom = null; break
          case 'right': addedRight -= diff; addedLeft += diff; addedTop = addedBottom = null; break
        }

        this.selectedElements.map(el => {
          const compTop = getComputedProp('top', el)
          const compBottom = getComputedProp('bottom', el)
          const compLeft = getComputedProp('left', el)
          const compRight = getComputedProp('right', el)

          const top = (addedTop && ((compTop + addedTop) >= 0) && ((compBottom + addedBottom) >= 0))
            ? (compTop + addedTop) : null
          const bottom = (addedBottom && ((compBottom + addedBottom) >= 0) && ((compTop + addedTop) >= 0))
            ? (compBottom + addedBottom) : null
          const left = (addedLeft && ((compLeft + addedLeft) >= 0) && ((compRight + addedRight) >= 0))
            ? (compLeft + addedLeft) : null
          const right = (addedRight && ((compRight + addedRight) >= 0) && ((compLeft + addedLeft) >= 0))
            ? (compRight + addedRight) : null

          if (top || bottom || left || right) {
            this.moveElement({ elId: el.id, pageId: this.page.id, top, bottom, left, right })
          }
        })
        this.rebaseSelectedElements()
      }
    }
  }
}
</script>
<style>
html.droppable,
html.droppable * {
  cursor: copy !important;
}
</style>
<style  scoped>
.view-editable {
    position: absolute;
    top: 0;
    bottom: 48px;
    left: 84px;
    right: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #505050;
    overflow: auto;
}
.view-editable .screen {

}
</style>
